package com.swiftops.common.service;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.conditions.update.UpdateChainWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.swiftops.common.model.User;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;

public abstract class AbstractMyBatisPlusService<T> extends ServiceImpl<BaseMapper<T>, T> {
    @Autowired
    private ThreadLocalUserService threadLocalUserService;

    @Override
    public boolean saveBatch(Collection<T> entityList, int batchSize) {
        for (T t : entityList) {
            this.insertModelAddInfo(t);
        }
        return super.saveBatch(entityList, batchSize);
    }

    @Override
    public boolean saveOrUpdate(T entity) {
        this.updateModelAddInfo(entity);
        return super.saveOrUpdate(entity);
    }

    @Override
    public boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize) {
        for (T t : entityList) {
            this.updateModelAddInfo(t);
        }
        return super.saveOrUpdateBatch(entityList, batchSize);
    }

    @Override
    public boolean updateBatchById(Collection<T> entityList, int batchSize) {
        for (T t : entityList) {
            this.updateModelAddInfo(t);
        }
        return super.updateBatchById(entityList, batchSize);
    }

    @Override
    public boolean save(T entity) {
        this.insertModelAddInfo(entity);
        return super.save(entity);
    }

    @Override
    public boolean updateById(T entity) {
        this.updateModelAddInfo(entity);
        return super.updateById(entity);
    }

    @Override
    public boolean update(Wrapper<T> updateWrapper) {
        T entity = updateWrapper.getEntity();
        this.updateModelAddInfo(entity);
        return super.update(updateWrapper);
    }

    @Override
    public boolean update(T entity, Wrapper<T> updateWrapper) {
        this.updateModelAddInfo(entity);
        return super.update(entity, updateWrapper);
    }

    @Override
    public boolean updateBatchById(Collection<T> entityList) {
        for (T t : entityList) {
            this.updateModelAddInfo(t);
        }
        return super.updateBatchById(entityList);
    }

    @Override
    public UpdateChainWrapper<T> update() {
        return super.update();
    }

    @Override
    public boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
        this.updateModelAddInfo(entity);
        return super.saveOrUpdate(entity, updateWrapper);
    }

    /**
     * 添加实体添加创建人、创建时间、更新人、更新时间
     *
     * @param model 实体对象
     */
    private void insertModelAddInfo(T model) {
        User user = threadLocalUserService.getUser();
        if (user != null) {
            this.addModelInfo(user.getUserId(), model, true);
        } else {
            this.addModelInfo(null, model, true);
        }
    }

    /**
     * 修改实体添加创建人、创建时间、更新人、更新时间
     *
     * @param model 实体对象
     */
    private void updateModelAddInfo(T model) {
        User user = threadLocalUserService.getUser();
        if (user != null) {
            this.addModelInfo(user.getUserId(), model, false);
        } else {
            this.addModelInfo(null, model, false);
        }
    }

    /**
     * 添加实体类的创建人、创建时间、更新人、更新时间
     *
     * @param id       人员ID
     * @param model    实体对象
     * @param isCreate 判断是否创建 0 不是，1 是
     */
    private void addModelInfo(String id, T model, boolean isCreate) {
        Field[] fs = model.getClass().getDeclaredFields();
        try {
            for (Field f : fs) {
                String fieldName = f.getName();
                if (isCreate && "createdBy".equals(fieldName)) {
                    f.setAccessible(true);
                    f.set(model, id);
                }
                if (isCreate && "createdAt".equals(fieldName)) {
                    f.setAccessible(true);
                    f.set(model, new Date());
                }
                if (isCreate && "deleteFlag".equals(fieldName)) {
                    f.setAccessible(true);
                    f.set(model, "0");
                }
                if ("updatedBy".equals(fieldName)) {
                    f.setAccessible(true);
                    f.set(model, id);
                }
                if ("updatedAt".equals(fieldName)) {
                    f.setAccessible(true);
                    f.set(model, new Date());
                }
            }
        } catch (IllegalAccessException e) {
            log.error(e.getMessage());
        }
    }
}
